#include "serializer/serializer.h"

#include <gtest/gtest.h>

#include <algorithm>
#include <array>
#include <chrono>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <map>
#include <numeric>
#include <optional>
#include <random>
#include <set>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace serializer;

// C++17 检测 traits：size()/data()/value_type 与相等可比较
namespace detail_perf
{
template <typename, typename = void>
struct has_size : std::false_type
{
};

template <typename T>
struct has_size<T, std::void_t<decltype(std::declval<const T &>().size())>> : std::true_type
{
};

template <typename, typename = void>
struct has_data : std::false_type
{
};

template <typename T>
struct has_data<T, std::void_t<decltype(std::declval<const T &>().data())>> : std::true_type
{
};

template <typename, typename = void>
struct has_value_type : std::false_type
{
};

template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type
{
};

template <typename, typename = void>
struct is_equality_comparable : std::false_type
{
};

template <typename T>
struct is_equality_comparable<
    T,
    std::void_t<decltype(std::declval<const T &>() == std::declval<const T &>())>> : std::true_type
{
};
} // namespace detail_perf

/**
 * 复杂嵌套数据结构体，用于性能测试
 */
struct ComplexData
{
    std::vector<std::string> strings;
    std::map<int, std::vector<double>> nested_map;
    std::array<int, 100> fixed_array;

    /**
     * 序列化ComplexData结构体
     * @param writer 写入器
     * @param options 序列化选项
     */
    template <typename Writer>
    void serialize(Writer & writer, const default_options & options = {}) const
    {
        serializer::serialize(writer, strings, options);
        serializer::serialize(writer, nested_map, options);
        serializer::serialize(writer, fixed_array, options);
    }

    /**
     * 反序列化ComplexData结构体
     * @param reader 读取器
     * @param options 反序列化选项
     * @return 反序列化的ComplexData实例
     */
    template <typename Reader>
    static ComplexData deserialize(Reader & reader, const default_options & options = {})
    {
        ComplexData result;
        result.strings = serializer::deserialize<std::vector<std::string>>(reader, options);
        result.nested_map =
            serializer::deserialize<std::map<int, std::vector<double>>>(reader, options);
        result.fixed_array = serializer::deserialize<std::array<int, 100>>(reader, options);
        return result;
    }

    // 为性能测试提供相等比较，用于数据完整性断言
    bool operator==(const ComplexData & other) const
    {
        return strings == other.strings && nested_map == other.nested_map &&
               fixed_array == other.fixed_array;
    }
};

/**
 * 混合数据类型结构体，用于性能测试
 */
struct MixedData
{
    std::vector<int> integers;
    std::vector<double> doubles;
    std::vector<std::string> strings;
    std::map<std::string, std::vector<int>> string_to_ints;
    std::optional<std::array<float, 50>> optional_array;
    std::tuple<int, std::string, double> tuple_data;

    /**
     * 序列化MixedData结构体
     * @param writer 写入器
     * @param options 序列化选项
     */
    template <typename Writer>
    void serialize(Writer & writer, const default_options & options = {}) const
    {
        serializer::serialize(writer, integers, options);
        serializer::serialize(writer, doubles, options);
        serializer::serialize(writer, strings, options);
        serializer::serialize(writer, string_to_ints, options);
        serializer::serialize(writer, optional_array, options);
        serializer::serialize(writer, tuple_data, options);
    }

    /**
     * 反序列化MixedData结构体
     * @param reader 读取器
     * @param options 反序列化选项
     * @return 反序列化的MixedData实例
     */
    template <typename Reader>
    static MixedData deserialize(Reader & reader, const default_options & options = {})
    {
        MixedData result;
        result.integers = serializer::deserialize<std::vector<int>>(reader, options);
        result.doubles = serializer::deserialize<std::vector<double>>(reader, options);
        result.strings = serializer::deserialize<std::vector<std::string>>(reader, options);
        result.string_to_ints =
            serializer::deserialize<std::map<std::string, std::vector<int>>>(reader, options);
        result.optional_array =
            serializer::deserialize<std::optional<std::array<float, 50>>>(reader, options);
        result.tuple_data =
            serializer::deserialize<std::tuple<int, std::string, double>>(reader, options);
        return result;
    }

    // 为性能测试提供相等比较，用于数据完整性断言
    bool operator==(const MixedData & other) const
    {
        return integers == other.integers && doubles == other.doubles && strings == other.strings &&
               string_to_ints == other.string_to_ints && optional_array == other.optional_array &&
               tuple_data == other.tuple_data;
    }
};

/**
 * 性能测试基类，提供通用的性能测量工具
 */
class PerformanceTestBase : public ::testing::Test
{
protected:
    using Clock = std::chrono::high_resolution_clock;
    using Duration = std::chrono::microseconds;

    struct PerformanceMetrics
    {
        Duration serialize_time{0};
        Duration deserialize_time{0};
        std::size_t serialized_size = 0;
        std::size_t original_size = 0;

        double compression_ratio() const
        {
            return original_size > 0 ? static_cast<double>(serialized_size) / original_size : 0.0;
        }

        double serialize_throughput_mbps() const
        {
            if (serialize_time.count() == 0)
                return 0.0;
            double mb_per_second = (static_cast<double>(original_size) / (1024.0 * 1024.0)) /
                                   (static_cast<double>(serialize_time.count()) / 1'000'000.0);
            return mb_per_second;
        }

        double deserialize_throughput_mbps() const
        {
            if (deserialize_time.count() == 0)
                return 0.0;
            double mb_per_second = (static_cast<double>(original_size) / (1024.0 * 1024.0)) /
                                   (static_cast<double>(deserialize_time.count()) / 1'000'000.0);
            return mb_per_second;
        }
    };

    template <typename T>
    PerformanceMetrics measure_roundtrip_performance(const T & data,
                                                     const default_options & options = {})
    {
        PerformanceMetrics metrics;
        metrics.original_size = estimate_size(data);

        // 测量序列化性能
        vector_writer writer;
        auto start = Clock::now();
        serialize(writer, data, options);
        auto end = Clock::now();
        metrics.serialize_time = std::chrono::duration_cast<Duration>(end - start);
        metrics.serialized_size = writer.data().size();

        // 测量反序列化性能
        vector_reader reader(writer.data());
        start = Clock::now();
        auto deserialized_data = deserialize<T>(reader, options);
        end = Clock::now();
        metrics.deserialize_time = std::chrono::duration_cast<Duration>(end - start);

        // 验证数据完整性（C++17 下使用检测 trait 替代 concepts）
        if constexpr (detail_perf::is_equality_comparable<T>::value)
        {
            EXPECT_EQ(data, deserialized_data);
        }

        return metrics;
    }

    template <typename T>
    std::size_t estimate_size(const T & data)
    {
        // 对已知复合类型进行专门估算，避免误探测 size()/value_type
        if constexpr (std::is_same_v<T, ComplexData>)
        {
            std::size_t total = 0;
            for (const auto & s : data.strings)
                total += s.size();
            total += data.fixed_array.size() * sizeof(int);
            for (const auto & kv : data.nested_map)
            {
                total += sizeof(int); // 键的大小
                total += kv.second.size() * sizeof(double);
            }
            return total;
        }
        else if constexpr (std::is_same_v<T, MixedData>)
        {
            std::size_t total = 0;
            total += data.integers.size() * sizeof(int);
            total += data.doubles.size() * sizeof(double);
            for (const auto & s : data.strings)
                total += s.size();
            for (const auto & kv : data.string_to_ints)
            {
                total += kv.first.size();
                total += kv.second.size() * sizeof(int);
            }
            if (data.optional_array.has_value())
            {
                total += data.optional_array->size() * sizeof(float);
            }
            total += sizeof(int) + std::get<1>(data.tuple_data).size() + sizeof(double);
            return total;
        }
        else if constexpr (std::is_arithmetic_v<T>)
        {
            return sizeof(T);
        }
        else if constexpr (detail_perf::has_size<T>::value)
        {
            if constexpr (detail_perf::has_data<T>::value && detail_perf::has_value_type<T>::value)
            {
                return data.size() * sizeof(typename T::value_type);
            }
            else
            {
                return data.size() * 8; // 估算
            }
        }
        else
        {
            return sizeof(T);
        }
    }
    void print_metrics(const std::string & label, const PerformanceMetrics & m) const
    {
        std::cout << "\n=== " << label << " ===\n";
        std::cout << "Serialize time: " << m.serialize_time.count() << " μs\n";
        std::cout << "Deserialize time: " << m.deserialize_time.count() << " μs\n";
        std::cout << "Serialized size: " << m.serialized_size << " bytes\n";
        std::cout << "Original size: " << m.original_size << " bytes\n";
        std::cout << "Compression ratio: " << std::fixed << std::setprecision(2)
                  << m.compression_ratio() << "\n";
        std::cout << "Serialize throughput: " << std::fixed << std::setprecision(2)
                  << m.serialize_throughput_mbps() << " MB/s\n";
        std::cout << "Deserialize throughput: " << std::fixed << std::setprecision(2)
                  << m.deserialize_throughput_mbps() << " MB/s\n";
    }
};

/**
 * 测试大型向量的序列化性能
 */
TEST_F(PerformanceTestBase, large_vector_performance)
{
    constexpr std::size_t vector_size = 1000000;
    std::vector<int> large_vector(vector_size);

    // 填充随机数据
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dis(1, 1000);

    std::generate(large_vector.begin(), large_vector.end(), [&]() { return dis(gen); });

    auto metrics = measure_roundtrip_performance(large_vector);
    print_metrics("Large Vector (1M integers)", metrics);

    // 性能断言
    EXPECT_LT(metrics.serialize_time.count(), 100000);      // 小于100ms
    EXPECT_LT(metrics.deserialize_time.count(), 100000);    // 小于100ms
    EXPECT_GT(metrics.serialize_throughput_mbps(), 10.0);   // 大于10MB/s
    EXPECT_GT(metrics.deserialize_throughput_mbps(), 10.0); // 大于10MB/s
}

/**
 * 测试大型字符串的序列化性能
 */
TEST_F(PerformanceTestBase, large_string_performance)
{
    constexpr std::size_t string_size = 1000000;
    std::string large_string;
    large_string.reserve(string_size);

    // 生成随机字符串
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<char> dis('a', 'z');

    for (std::size_t i = 0; i < string_size; ++i)
    {
        large_string.push_back(dis(gen));
    }

    auto metrics = measure_roundtrip_performance(large_string);
    print_metrics("Large String (1MB)", metrics);

    // 性能断言
    EXPECT_LT(metrics.serialize_time.count(), 50000);   // 小于50ms
    EXPECT_LT(metrics.deserialize_time.count(), 50000); // 小于50ms
}

/**
 * 测试嵌套结构的序列化性能
 */
TEST_F(PerformanceTestBase, nested_structure_performance)
{
    ComplexData data;

    // 填充数据
    for (int i = 0; i < 1000; ++i)
    {
        data.strings.push_back("test_string_" + std::to_string(i));
        data.nested_map[i] = std::vector<double>(10, static_cast<double>(i) * 1.5);
    }

    std::iota(data.fixed_array.begin(), data.fixed_array.end(), 1);

    auto metrics = measure_roundtrip_performance(data);
    print_metrics("Complex Nested Structure", metrics);

    // 性能断言
    EXPECT_LT(metrics.serialize_time.count(), 200000);   // 小于200ms
    EXPECT_LT(metrics.deserialize_time.count(), 200000); // 小于200ms
}

/**
 * 测试关联容器的序列化性能
 */
TEST_F(PerformanceTestBase, associative_container_performance)
{
    std::map<std::string, int> large_map;
    std::set<std::string> large_set;

    // 填充数据
    for (int i = 0; i < 100000; ++i)
    {
        std::string key = "key_" + std::to_string(i);
        large_map[key] = i;
        large_set.insert(key);
    }

    auto map_metrics = measure_roundtrip_performance(large_map);
    print_metrics("Large Map (100K entries)", map_metrics);

    auto set_metrics = measure_roundtrip_performance(large_set);
    print_metrics("Large Set (100K entries)", set_metrics);

    // 性能断言 - 放宽要求以适应不同的运行环境
    EXPECT_LT(map_metrics.serialize_time.count(), 60000000); // 小于60秒
    EXPECT_LT(set_metrics.serialize_time.count(), 60000000); // 小于60秒
}

/**
 * 测试无序容器的序列化性能
 */
TEST_F(PerformanceTestBase, unordered_container_performance)
{
    std::unordered_map<int, std::string> large_unordered_map;
    std::unordered_set<int> large_unordered_set;

    // 填充数据
    for (int i = 0; i < 100000; ++i)
    {
        large_unordered_map[i] = "value_" + std::to_string(i);
        large_unordered_set.insert(i);
    }

    auto map_metrics = measure_roundtrip_performance(large_unordered_map);
    print_metrics("Large Unordered Map (100K entries)", map_metrics);

    auto set_metrics = measure_roundtrip_performance(large_unordered_set);
    print_metrics("Large Unordered Set (100K entries)", set_metrics);
}

/**
 * 测试混合数据类型的序列化性能
 */
TEST_F(PerformanceTestBase, mixed_data_types_performance)
{
    MixedData data;

    // 填充数据
    data.integers.resize(10000);
    std::iota(data.integers.begin(), data.integers.end(), 1);

    data.doubles.resize(10000);
    std::generate(data.doubles.begin(),
                  data.doubles.end(),
                  []() { return static_cast<double>(rand()) / RAND_MAX; });

    for (int i = 0; i < 1000; ++i)
    {
        data.strings.push_back("mixed_string_" + std::to_string(i));
        data.string_to_ints["key_" + std::to_string(i)] = {i, i * 2, i * 3};
    }

    data.optional_array = std::array<float, 50>{};
    std::iota(data.optional_array->begin(), data.optional_array->end(), 1.0f);

    data.tuple_data = std::make_tuple(42, "tuple_string", 3.14159);

    auto metrics = measure_roundtrip_performance(data);
    print_metrics("Mixed Data Types", metrics);
}

/**
 * 测试字节序对性能的影响
 */
TEST_F(PerformanceTestBase, byte_order_performance_impact)
{
    std::vector<std::uint64_t> large_integers(100000);
    std::iota(large_integers.begin(), large_integers.end(), 1);

    // 测试小端序
    auto little_endian_options = default_options{}.with_byte_order(byte_order::little_endian);
    auto little_endian_metrics =
        measure_roundtrip_performance(large_integers, little_endian_options);
    print_metrics("Little Endian", little_endian_metrics);

    // 测试大端序
    auto big_endian_options = default_options{}.with_byte_order(byte_order::big_endian);
    auto big_endian_metrics = measure_roundtrip_performance(large_integers, big_endian_options);
    print_metrics("Big Endian", big_endian_metrics);

    // 测试本机字节序（改为使用完整流 API，以允许 native 在头部具体化）
    auto native_options = default_options{}.with_byte_order(byte_order::native);
    PerformanceMetrics native_metrics;
    native_metrics.original_size = estimate_size(large_integers);
    {
        vector_writer writer;
        auto start_native = Clock::now();
        serialize_stream(writer, large_integers, native_options);
        auto end_native = Clock::now();
        native_metrics.serialize_time =
            std::chrono::duration_cast<Duration>(end_native - start_native);
        native_metrics.serialized_size = writer.data().size();
        vector_reader reader(writer.data());
        start_native = Clock::now();
        auto deserialized_native =
            deserialize_stream<std::vector<std::uint64_t>>(reader, default_options{});
        end_native = Clock::now();
        native_metrics.deserialize_time =
            std::chrono::duration_cast<Duration>(end_native - start_native);
        EXPECT_EQ(deserialized_native, large_integers);
    }
    print_metrics("Native Endian (stream)", native_metrics);

    // 本机字节序通常是最快的，但允许一定的误差范围
    // 检查所有测试都在合理时间内完成
    EXPECT_LT(native_metrics.serialize_time.count(), 5000000);        // 小于5秒
    EXPECT_LT(little_endian_metrics.serialize_time.count(), 5000000); // 小于5秒
    EXPECT_LT(big_endian_metrics.serialize_time.count(), 5000000);    // 小于5秒
}

/**
 * 测试变长整数编码的性能影响
 */
TEST_F(PerformanceTestBase, varint_performance)
{
    std::vector<std::uint64_t> mixed_integers;

    // 小整数（1-2字节变长编码）
    for (int i = 0; i < 10000; ++i)
    {
        mixed_integers.push_back(static_cast<uint64_t>(i));
    }

    // 大整数（8字节固定编码）
    for (int i = 0; i < 1000; ++i)
    {
        mixed_integers.push_back(static_cast<uint64_t>(i) * 1000000000ULL);
    }

    // 测试启用变长整数
    auto varint_options = default_options{}.with_varint_lengths(true);
    auto varint_metrics = measure_roundtrip_performance(mixed_integers, varint_options);
    print_metrics("With Varint", varint_metrics);

    // 测试禁用变长整数
    auto fixed_options = default_options{}.with_varint_lengths(false);
    auto fixed_metrics = measure_roundtrip_performance(mixed_integers, fixed_options);
    print_metrics("Without Varint", fixed_metrics);

    // 对于这种数据分布，变长整数应该提供更好的压缩
    EXPECT_LT(varint_metrics.serialized_size, fixed_metrics.serialized_size);
}

/**
 * 测试内存使用效率
 */
TEST_F(PerformanceTestBase, memory_efficiency_test)
{
    // 创建大型数据结构
    constexpr std::size_t vector_size = 1000000;
    std::vector<int> large_vector(vector_size, 42);

    // 测量序列化前的内存使用
    std::size_t original_memory = large_vector.size() * sizeof(int);

    // 序列化
    vector_writer writer;
    serialize(writer, large_vector, default_options{});

    // 测量序列化后的内存使用
    std::size_t serialized_memory = writer.data().size();

    std::cout << "\n=== Memory Efficiency Test ===\n";
    std::cout << "Original memory: " << original_memory << " bytes\n";
    std::cout << "Serialized memory: " << serialized_memory << " bytes\n";
    std::cout << "Memory efficiency: " << std::fixed << std::setprecision(2)
              << (static_cast<double>(serialized_memory) / original_memory) << "\n";

    // 序列化后的内存应该接近原始内存（考虑到长度前缀等开销）
    EXPECT_LT(serialized_memory, original_memory * 1.1); // 不超过10%的开销
}

/**
 * 测试批量操作性能
 */
TEST_F(PerformanceTestBase, batch_operations_performance)
{
    constexpr std::size_t num_batches = 1000;
    constexpr std::size_t batch_size = 1000;
    constexpr std::size_t total_elements = num_batches * batch_size;

    // 创建多个小批次
    std::vector<std::vector<int>> small_batches;
    for (std::size_t i = 0; i < num_batches; ++i)
    {
        std::vector<int> batch(batch_size);
        std::iota(batch.begin(), batch.end(), static_cast<int>(i * batch_size));
        small_batches.push_back(std::move(batch));
    }

    // 创建一个大批次
    std::vector<int> large_batch;
    large_batch.reserve(total_elements);
    for (const auto & batch : small_batches)
    {
        large_batch.insert(large_batch.end(), batch.begin(), batch.end());
    }

    // 测试单次大型序列化
    auto large_batch_metrics = measure_roundtrip_performance(large_batch);
    print_metrics("Single Large Batch", large_batch_metrics);

    // 测试多次小型序列化
    auto start = Clock::now();
    vector_writer writer;
    for (const auto & batch : small_batches)
    {
        serialize(writer, batch, default_options{});
    }
    auto serialize_end = Clock::now();

    vector_reader reader(writer.data());
    std::vector<std::vector<int>> deserialized_batches;
    for (std::size_t i = 0; i < num_batches; ++i)
    {
        auto batch = deserialize<std::vector<int>>(reader, default_options{});
        deserialized_batches.push_back(std::move(batch));
    }
    auto deserialize_end = Clock::now();

    PerformanceMetrics small_batches_metrics;
    small_batches_metrics.serialize_time =
        std::chrono::duration_cast<Duration>(serialize_end - start);
    small_batches_metrics.deserialize_time =
        std::chrono::duration_cast<Duration>(deserialize_end - serialize_end);
    small_batches_metrics.serialized_size = writer.data().size();
    small_batches_metrics.original_size = total_elements * sizeof(int);

    print_metrics("Multiple Small Batches", small_batches_metrics);

    // 验证数据完整性
    ASSERT_EQ(small_batches.size(), deserialized_batches.size());
    for (std::size_t i = 0; i < small_batches.size(); ++i)
    {
        EXPECT_EQ(small_batches[i], deserialized_batches[i]);
    }

    // 单次大型序列化通常应该更快
    EXPECT_LT(large_batch_metrics.serialize_time, small_batches_metrics.serialize_time);
}

/**
 * 压力测试：连续操作
 */
TEST_F(PerformanceTestBase, stress_test_continuous_operations)
{
    constexpr std::size_t num_iterations = 1000;
    constexpr std::size_t data_size = 10000;

    std::vector<int> test_data(data_size);
    std::iota(test_data.begin(), test_data.end(), 1);

    auto start = Clock::now();

    for (std::size_t i = 0; i < num_iterations; ++i)
    {
        vector_writer writer;
        serialize(writer, test_data, default_options{});

        vector_reader reader(writer.data());
        auto deserialized = deserialize<std::vector<int>>(reader, default_options{});

        // 验证数据完整性
        ASSERT_EQ(test_data, deserialized);
    }

    auto end = Clock::now();
    auto total_time = std::chrono::duration_cast<Duration>(end - start);

    std::cout << "\n=== Stress Test Results ===\n";
    std::cout << "Iterations: " << num_iterations << "\n";
    std::cout << "Data size per iteration: " << data_size << " integers\n";
    std::cout << "Total time: " << total_time.count() << " μs\n";
    std::cout << "Average time per iteration: " << (total_time.count() / num_iterations) << " μs\n";

    // 平均每次迭代应该在合理时间内完成
    // 确保总时间为正数，并且平均时间合理
    EXPECT_GT(total_time.count(), 0); // 总时间应该为正数
    if (total_time.count() > 0)
    {
        EXPECT_LT(total_time.count() / num_iterations, 100000); // 小于100ms每次迭代
    }
}